import BasePlugin from './BasePlugin';

/**
 * 缩放插件 - 处理画布缩放和平移
 */
export default class ZoomPlugin extends BasePlugin {
    constructor() {
        super();
        this.minZoom = 0.1;
        this.maxZoom = 5;
        this.zoomStep = 0.1;
        this.currentZoom = 1;
        this.isPanning = false;
        this.lastPosX = 0;
        this.lastPosY = 0;
        this.viewportTransform = [1, 0, 0, 1, 0, 0];
    }

    /**
     * 初始化插件
     */
    init(editor) {
        super.init(editor);
        this._setupEventListeners();
    }

    /**
     * 启用缩放功能
     */
    enable() {
        super.enable();
        this.canvas.set({
            allowTouchScrolling: true
        });
    }

    /**
     * 禁用缩放功能
     */
    disable() {
        super.disable();
        this.canvas.set({
            allowTouchScrolling: false
        });
    }

    /**
     * 设置缩放范围
     */
    setZoomRange(min, max) {
        this.minZoom = min;
        this.maxZoom = max;
    }

    /**
     * 设置缩放步长
     */
    setZoomStep(step) {
        this.zoomStep = step;
    }

    /**
     * 放大
     */
    zoomIn(point) {
        if (!this.isEnabled() || !this.canvas) return;

        const zoom = this.currentZoom + this.zoomStep;
        this.zoomTo(Math.min(zoom, this.maxZoom), point);
    }

    /**
     * 缩小
     */
    zoomOut(point) {
        if (!this.isEnabled() || !this.canvas) return;

        const zoom = this.currentZoom - this.zoomStep;
        this.zoomTo(Math.max(zoom, this.minZoom), point);
    }

    /**
     * 缩放到指定比例
     */
    zoomTo(zoom, point) {
        if (!this.isEnabled() || !this.canvas) return;

        // 限制缩放范围
        zoom = Math.min(Math.max(zoom, this.minZoom), this.maxZoom);

        // 如果没有指定缩放中心点，则使用画布中心
        if (!point) {
            point = {
                x: this.canvas.width / 2,
                y: this.canvas.height / 2
            };
        }

        const zoomPoint = {
            x: point.x - this.viewportTransform[4],
            y: point.y - this.viewportTransform[5]
        };

        const factor = zoom / this.currentZoom;

        this.viewportTransform[0] = zoom;
        this.viewportTransform[3] = zoom;
        this.viewportTransform[4] += zoomPoint.x - zoomPoint.x * factor;
        this.viewportTransform[5] += zoomPoint.y - zoomPoint.y * factor;

        this.canvas.setViewportTransform(this.viewportTransform);
        this.currentZoom = zoom;

        this._emitZoomEvent('zoom', { zoom, point });
    }

    /**
     * 重置缩放
     */
    resetZoom() {
        if (!this.isEnabled() || !this.canvas) return;

        this.viewportTransform = [1, 0, 0, 1, 0, 0];
        this.canvas.setViewportTransform(this.viewportTransform);
        this.currentZoom = 1;

        this._emitZoomEvent('reset');
    }

    /**
     * 适应画布
     */
    zoomToFit() {
        if (!this.isEnabled() || !this.canvas) return;

        const objects = this.canvas.getObjects();
        if (objects.length === 0) return;

        const bounds = this._getObjectsBounds(objects);
        const canvasWidth = this.canvas.width;
        const canvasHeight = this.canvas.height;

        const scaleX = canvasWidth / bounds.width;
        const scaleY = canvasHeight / bounds.height;
        const zoom = Math.min(scaleX, scaleY) * 0.9; // 留出10%的边距

        this.zoomTo(zoom);
        this.panTo(bounds.left + bounds.width / 2, bounds.top + bounds.height / 2);

        this._emitZoomEvent('fit');
    }

    /**
     * 平移到指定位置
     */
    panTo(x, y) {
        if (!this.isEnabled() || !this.canvas) return;

        const center = {
            x: this.canvas.width / 2,
            y: this.canvas.height / 2
        };

        this.viewportTransform[4] = center.x - x * this.currentZoom;
        this.viewportTransform[5] = center.y - y * this.currentZoom;

        this.canvas.setViewportTransform(this.viewportTransform);
        this._emitZoomEvent('pan', { x, y });
    }

    /**
     * 获取当前缩放比例
     */
    getZoom() {
        return this.currentZoom;
    }

    /**
     * 获取对象边界
     */
    _getObjectsBounds(objects) {
        let minX = Infinity;
        let minY = Infinity;
        let maxX = -Infinity;
        let maxY = -Infinity;

        objects.forEach(obj => {
            const bounds = obj.getBoundingRect();
            minX = Math.min(minX, bounds.left);
            minY = Math.min(minY, bounds.top);
            maxX = Math.max(maxX, bounds.left + bounds.width);
            maxY = Math.max(maxY, bounds.top + bounds.height);
        });

        return {
            left: minX,
            top: minY,
            width: maxX - minX,
            height: maxY - minY
        };
    }

    /**
     * 发送缩放事件
     */
    _emitZoomEvent(type, data = {}) {
        this.editor.emit('zoom:applied', {
            type,
            zoom: this.currentZoom,
            ...data
        });
    }

    /**
     * 设置事件监听
     */
    _setupEventListeners() {
        if (!this.canvas) return;

        // 监听鼠标滚轮事件
        this.canvas.on('mouse:wheel', (e) => {
            if (!this.isEnabled()) return;

            e.e.preventDefault();
            e.e.stopPropagation();

            const delta = e.e.deltaY;
            const point = this.canvas.getPointer(e.e);

            if (delta > 0) {
                this.zoomOut(point);
            } else {
                this.zoomIn(point);
            }
        });

        // 监听鼠标按下事件
        this.canvas.on('mouse:down', (e) => {
            if (!this.isEnabled() || e.target) return;

            this.isPanning = true;
            this.lastPosX = e.e.clientX;
            this.lastPosY = e.e.clientY;
            this.canvas.setCursor('grabbing');
        });

        // 监听鼠标移动事件
        this.canvas.on('mouse:move', (e) => {
            if (!this.isEnabled() || !this.isPanning) return;

            const deltaX = e.e.clientX - this.lastPosX;
            const deltaY = e.e.clientY - this.lastPosY;

            this.viewportTransform[4] += deltaX;
            this.viewportTransform[5] += deltaY;

            this.canvas.setViewportTransform(this.viewportTransform);
            this._emitZoomEvent('pan', { deltaX, deltaY });

            this.lastPosX = e.e.clientX;
            this.lastPosY = e.e.clientY;
        });

        // 监听鼠标松开事件
        this.canvas.on('mouse:up', () => {
            if (!this.isEnabled()) return;

            this.isPanning = false;
            this.canvas.setCursor('default');
        });

        // 监听画布大小变化事件
        window.addEventListener('resize', this._handleResize.bind(this));
    }

    /**
     * 处理画布大小变化
     */
    _handleResize() {
        if (!this.isEnabled() || !this.canvas) return;

        // 保持当前视口中心点不变
        const center = {
            x: this.canvas.width / 2,
            y: this.canvas.height / 2
        };

        this.canvas.setDimensions({
            width: window.innerWidth,
            height: window.innerHeight
        });

        const newCenter = {
            x: this.canvas.width / 2,
            y: this.canvas.height / 2
        };

        this.viewportTransform[4] += newCenter.x - center.x;
        this.viewportTransform[5] += newCenter.y - center.y;

        this.canvas.setViewportTransform(this.viewportTransform);
    }

    /**
     * 销毁插件
     */
    destroy() {
        if (this.canvas) {
            window.removeEventListener('resize', this._handleResize);
            this.resetZoom();
        }
        super.destroy();
    }
} 